package com.zhixun.zhlq.utils;


import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Http请求工具类
 *
 * @author eollse
 */
@Slf4j
public class HttpClientUtil {

    private final int CONNECTION_TIME_OUT = 3000;
    private final int REQUEST_TIME_OUT = 5000;
    private final int SOCKET_TIME_OUT = 5000;

    private final int OK_CODE = 200;

    public RequestConfig setConfig() {
        //设置请求超时
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(CONNECTION_TIME_OUT).setConnectionRequestTimeout(REQUEST_TIME_OUT)
                .setSocketTimeout(SOCKET_TIME_OUT).build();
        return requestConfig;
    }

    /**
     * 处理get请求
     * @param url 请求路径
     * @param encoding
     * @param headers 请求头
     * @param proxyIp 代理ip
     * @param proxyPort 代理端口
     * @return
     */
    public String get(String url, String encoding, Map<String, String> headers, String proxyIp, Integer proxyPort) {
        if (proxyPort > 0) {
            url = "http://" + proxyIp + ":" +proxyPort+"/" + url.substring(url.indexOf("//"));
        }
        //请求结果
        CloseableHttpResponse response;
        String content = "";
        try {
            CloseableHttpClient httpclient = HttpClients.createDefault();
//            实例化get方法
            HttpGet httpget = new HttpGet(url);
            if (headers != null) {
                Set<String> headerKeys = headers.keySet();
                for (String headerKey : headerKeys) {
                    httpget.setHeader(headerKey, headers.get(headerKey));
                }
            }
            httpget.setConfig(setConfig());
            //执行get方法
            response = httpclient.execute(httpget);
            if (response.getStatusLine().getStatusCode() == OK_CODE) {
                content = EntityUtils.toString(response.getEntity(), encoding);
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            log.error("连接或读取超时：" + e.toString());
        } catch (ConnectTimeoutException e) {
            e.printStackTrace();
            log.error("连接超时：" + e.toString());
        } catch (NoHttpResponseException e) {
            e.printStackTrace();
            log.error("没有响应：" + e.toString());
        } catch (UnknownHostException e) {
            e.printStackTrace();
            log.error("找不到服务器：" + e.toString());
        } catch (HttpHostConnectException e) {
            e.printStackTrace();
            log.error("连接超时：" + e.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }


    /**
     * 处理post请求.
     *
     * @param url    请求路径
     * @param params 参数
     * @return json
     */
    public String post(String url, String encoding, Map<String, String> params, String proxyIp, Integer proxyPort) {
        if (proxyPort > 0) {
            url = "http://" + proxyIp + ":" +proxyPort+"/" + url.substring(url.indexOf("//"));
        }
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(setConfig());
        //处理参数
        List<NameValuePair> nvps = new ArrayList<>();
        Set<String> keySet = params.keySet();
        for (String key : keySet) {
            nvps.add(new BasicNameValuePair(key, params.get(key)));
        }
        //结果  
        CloseableHttpResponse response;
        String content = "";
        try {
            //提交的参数  
            UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(nvps, encoding);
            //将参数给post方法  
            httpPost.setEntity(uefEntity);
            //执行post方法  
            response = httpclient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == OK_CODE) {
                content = EntityUtils.toString(response.getEntity(), encoding);
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (SocketTimeoutException e) {
            log.error("连接或读取超时：" + e.toString());
        } catch (ConnectTimeoutException e) {
            log.error("连接超时：" + e.toString());
        } catch (NoHttpResponseException e) {
            log.error("没有响应：" + e.toString());
        } catch (UnknownHostException e) {
            log.error("找不到服务器：" + e.toString());
        } catch (HttpHostConnectException e) {
            log.error("连接超时：" + e.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 处理post请求.
     *
     * @param url    请求路径
     * @param params 参数
     * @return json
     */
    public String postByJson(String url, Map<String, String> headers, String params, String proxyIp, Integer proxyPort) {
        if (proxyPort > 0) {
            url = "http://" + proxyIp + ":" +proxyPort+"/" + url.substring(url.indexOf("//"));
        }
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(setConfig());
        httpPost.setHeader("Content-Type", "application/json");
        if (headers != null) {
            Set<String> headerKeys = headers.keySet();
            for (String headerKey : headerKeys) {
                httpPost.setHeader(headerKey, headers.get(headerKey));
            }
        }
        //结果
        CloseableHttpResponse response;
        String content = "";
        try {
            httpPost.setEntity(new StringEntity(params, "utf-8"));
            //执行post方法
            response = httpclient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == OK_CODE) {
                content = resultBody(response);
            } else {
                log.error("result-error:"+resultBody(response));
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }

    private String resultBody(CloseableHttpResponse response) throws IOException {
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = response.getEntity().getContent().read(buffer)) != -1) {
            result.write(buffer, 0, length);
        }
        return result.toString("utf-8");
    }

    /**
     * 图片下载
     *
     * @param url
     * @return
     */
    public InputStream downPicture(String url) {
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(setConfig());
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response;
        try {
            //执行get方法
            response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == OK_CODE) {
                return response.getEntity().getContent();
            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}